package com.hna.eking.AirlineServer.Platform.FileUpload;


import java.io.BufferedInputStream;
import java.io.Console;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.trace.Trace;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;

import com.hna.eking.AirlineServer.Exception.RunServiceException;
import com.hna.eking.AirlineServer.Mapper.AirportInfo;
import com.hna.eking.AirlineServer.Mapper.AirportInfoMapper;
import com.hna.eking.AirlineServer.Mapper.AreaInfo;
import com.hna.eking.AirlineServer.Mapper.CountryInfo;
import com.hna.eking.AirlineServer.Mapper.MapInfo;
import com.hna.eking.AirlineServer.Mapper.MapInfoMapper;
import com.hna.eking.AirlineServer.Service.MapInfoService;
import com.hna.eking.AirlineServer.Utils.ResponseSupport;

@Controller
@RequestMapping("/file/*")
public class FileController {
	
	Logger logger = LoggerFactory.getLogger(FileController.class);
	
	@Autowired
	MultipartResolver multipartResolver;
	
	@Autowired
	AirportInfoMapper airportDao;
	@Autowired
	private MapInfoService mapinfoService;
	@Autowired
	MapInfoMapper mapDao;
	
	final String DWNLD_TYPE_AIRPORT = "airport";
	final String DWNLD_TYPE_MAP = "map";
	final String DWNLD_TYPE_TILE = "tile";
	final String DWNLD_TYPE_TERRAIN = "terrain";
	final String DWNLD_TYPE_IMAGERY = "imagery";
	final String SYSTEM_AUTO_GEN = "SYSTEM";
	@Value("${visualcharts.file.uploadpath}")
	private String MapFilePath;
	
//	@RequestMapping(value="/downloads/{type}/{code}", method=RequestMethod.GET)
//	public void fileDownload(@PathVariable(value="code") String code,
//			@PathVariable(value="type") String type,
//			HttpServletRequest  request, HttpServletResponse response) {
//		String realPath = "";
//		if ("airport".equals(type)) {
//			AirportInfo airport = airportDao.selectByArptNo(code);
//			if (airport == null) {
//				response.setStatus(404);
//				return;
//			}
//			realPath = "/Users/jiangzhengzhou/HNA/Bin/Data/" + code + "_0.0.1.zip";
//		} else if ("map".equals(type)) {
//			MapInfo airlineMap = mapDao.selectByPrimaryKey(code).get(0);
//			if (airlineMap == null || airlineMap.getFilePath() == null) {
//				response.setStatus(404);
//				return;
//			}
//			realPath = "/Users/jiangzhengzhou/HNA/Bin/Data/" + 
//					airlineMap.getFilePath();
//		} else {
//			response.setStatus(404);
//			return;
//		}
//		String fileName = realPath.substring(realPath.lastIndexOf("/") + 1);
//		logger.info("ready download fileName: " + realPath);
//		response.setHeader("content-type", "application/octet-stream");
//		response.setContentType("application/octet-stream");
//		response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
//		InputStream in = null;
//		OutputStream out = null;
//		try {
//			byte[] buff = new byte[4096];
//			in = new BufferedInputStream(new FileInputStream(new File(realPath)));
//			out = response.getOutputStream();
//			int readlen =  in.read(buff);
//			while (readlen != -1) {
//				out.write(buff, 0, buff.length);
//				out.flush();
//				readlen = in.read(buff);
//			}
//			logger.info("download " + fileName + " success!");
//		} catch (FileNotFoundException e) {
//			response.setStatus(404);
//			logger.info("File Not Found: " + realPath);
//		} catch (IOException e) {
//			response.setStatus(404);
//			logger.info("IOException: " + e.getMessage());
//		} finally {
//            if (in != null) {
//                try {
//                	in.close();
//                } catch (IOException e) {
//                  e.printStackTrace();
//                }
//            }
//		}
//	}
	
	//获得压缩包列表，地形，影像
	//参数：{下载类型}/{下载地区}
	@RequestMapping(value= {"/list/{type}/{area}"}, method=RequestMethod.GET)
	public @ResponseBody ResponseSupport<String> fileList(@PathVariable(value="type", required = true) String type,
			@PathVariable(value="area", required = true) String area,
			HttpServletRequest request, HttpServletResponse response) {
		String dirname = "maps/" + type + "/" + area;
		File dirfile = new File(dirname);
		File[] zipfiles = dirfile.listFiles();
		StringBuffer filenames = new StringBuffer();
		
		for (int i = 0; i < zipfiles.length; i++) {
			if (zipfiles[i].getName().endsWith(".zip")) {
				filenames.append(zipfiles[i].getName());
				filenames.append(",");
			}
		}
		if (filenames.length() > 0) {
			filenames.delete(filenames.length() - 1, filenames.length());
		}
		ResponseSupport<String> rsp = new ResponseSupport<String>();
		rsp.setCode(200);
		rsp.setContent(filenames.toString());
		
		return rsp;
	}
	
	//下载压缩包，地形，影像
	//参数：{下载类型}/{下载地区}/{文件名}
	@RequestMapping(value= {"/downtile/{type}/{area}/{filename:.+}"}, method=RequestMethod.GET)
	public void tileDownloads(@PathVariable(value="type", required = true) String type,
			@PathVariable(value="area", required = true) String area,
			@PathVariable(value="filename", required = true) String filename,
			HttpServletRequest request, HttpServletResponse response) {
		StringBuffer filenameBuff = new StringBuffer("maps/");
		filenameBuff.append(type);
		filenameBuff.append("/");
		filenameBuff.append(area);
		filenameBuff.append("/");
		filenameBuff.append(filename);
		
		realDownload(response, filenameBuff.toString());
	}
	
	private void realDownload(HttpServletResponse response, String filePath){
		logger.info("ready download fileName: " + filePath);
		String filename = filePath.substring(filePath.lastIndexOf("/") + 1);
		response.setHeader("content-type", "application/octet-stream");
		response.setContentType("application/octet-stream");
		response.setHeader("Content-Disposition", "attachment;filename=" + filename);
		InputStream in = null;
		OutputStream out = null;
		try {
			byte[] buff = new byte[4096];
			in = new BufferedInputStream(new FileInputStream(new File(filePath)));
			out = response.getOutputStream();
			int readlen =  in.read(buff);
			while (readlen != -1) {
				out.write(buff, 0, buff.length);
				out.flush();
				readlen = in.read(buff);
			}
			logger.info("download " + filename + " success!");
		} catch (FileNotFoundException e) {
			response.setStatus(RunServiceException.REQ_NOT_FOUND);
			logger.info("File Not Found: " + filePath);
		} catch (IOException e) {
			response.setStatus(RunServiceException.REQ_NOT_FOUND);
			logger.info("IOException: " + e.getMessage());
		} finally {
            if (in != null) {
                try {
                	in.close();
                } catch (IOException e) {
                  e.printStackTrace();
                }
            }
		}
	}
	
	//下载航图，机场，航图
	@RequestMapping(value= {"/download/{type}/{code}", "/download/{type}"}, method=RequestMethod.GET)
	public void fileDownloads(@PathVariable(value="code", required = false) String code,
			@PathVariable(value="type") String type,
			HttpServletRequest request, HttpServletResponse response) {
		String realPath = "";
		String fileName = "";
		
		/*下载机场航图压缩包*/
		if (DWNLD_TYPE_AIRPORT.equals(type)) {
			AirportInfo airport = airportDao.selectByArptNo(code);
			if (airport == null) {
				logger.info("airport not found: " + code);
				response.setStatus(RunServiceException.REQ_NOT_FOUND);
				return;
			}
			realPath = String.format("%s/zip/%s_%08d.zip", MapFilePath, airport.getAirportCode(), airport.getMapVersion());
			fileName = realPath.substring(realPath.lastIndexOf("/") + 1);
			File fp = new File(realPath);
			/*如果文件不存在，则打包*/
			if(!fp.exists()) {
				String FileTmp = realPath + "tmp";
				File fileTmp = new File(FileTmp);
				if(fileTmp.exists()) {//临时文件存在 ，则等待另外一个进程打包完成
					int i = 0;
					for(i = 0; i< 60 && !fp.exists(); i++) {//等待其他进程打包完成，进行下载
						logger.info("waitting another process compress the file");
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							response.setStatus(RunServiceException.REQ_NOT_FOUND);
							return;
						}
					}
					if (i >= 60) {
						response.setStatus(RunServiceException.REQ_NOT_FOUND);
						return;
					}
				} else {
					mapinfoService.generateMapZip(airport.getAirportCode(), SYSTEM_AUTO_GEN);
				}
			}
		} else if (DWNLD_TYPE_MAP.equals(type)) {//下载单张航图
			MapInfo airlineMap = mapDao.selectByPrimaryKey(code).get(0);
			if (airlineMap == null || airlineMap.getFilePath() == null) {
				response.setStatus(RunServiceException.REQ_NOT_FOUND);
				return;
			}
			realPath = airlineMap.getFilePath();
			fileName = realPath.substring(realPath.lastIndexOf("/") + 1);
		} else if (DWNLD_TYPE_TILE.equals(type)) {
			realPath = "maps/tile.zip";
			fileName = "tile";
		} else {
			response.setStatus(RunServiceException.REQ_NOT_FOUND);
			return;
		}
		logger.info("ready download fileName: " + realPath);
		response.setHeader("content-type", "application/octet-stream");
		response.setContentType("application/octet-stream");
		response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
		InputStream in = null;
		OutputStream out = null;
		try {
			byte[] buff = new byte[4096];
			in = new BufferedInputStream(new FileInputStream(new File(realPath)));
			out = response.getOutputStream();
			int readlen =  in.read(buff);
			while (readlen != -1) {
				out.write(buff, 0, buff.length);
				out.flush();
				readlen = in.read(buff);
			}
			logger.info("download " + fileName + " success!");
		} catch (FileNotFoundException e) {
			response.setStatus(RunServiceException.REQ_NOT_FOUND);
			logger.info("File Not Found: " + realPath);
		} catch (IOException e) {
			response.setStatus(RunServiceException.REQ_NOT_FOUND);
			logger.info("IOException: " + e.getMessage());
		} finally {
            if (in != null) {
                try {
                	in.close();
                } catch (IOException e) {
                  e.printStackTrace();
                }
            }
		}
	}
	@RequestMapping(value="/upload", method=RequestMethod.POST)
    public @ResponseBody ResponseSupport<String> fileUpload(
    		@RequestParam(value="mapinfo",required=false) String mapinfo,
    		@RequestParam("upfile") MultipartFile file  //1.会报类型不对的错误！！2.根本就找不到文件
    		,HttpServletRequest request
    		) throws Exception{
		/**
		 * 调试时使用的手动获取方式，前提是spring管理resolver
		 */
//		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request;
//		MultipartFile file = multipartRequest.getFile("upfile");  
		String realPath = "uploadfiles/";//得到文件上传目的位置的真实路径
        File dir = new File(realPath);
        if(!dir.exists()){
        	dir.mkdir();   //如果该目录不存在，就创建此抽象路径名指定的目录。 
        }
        String prefix = UUID.randomUUID().toString();
        prefix = prefix.replace("-","");
        String fileName = prefix+"_"+file.getOriginalFilename();//使用UUID加前缀命名文件，防止名字重复被覆盖
        
        File outFile =  new File(realPath+"\\"+fileName);
        file.transferTo(outFile);
        
		ResponseSupport<String> responseSupport = new ResponseSupport<String>();
		responseSupport.setCode(200);
		responseSupport.setMessage("upload success！");
    
        return responseSupport;
    }
	
	@RequestMapping(value = "/uploadProcess", method = RequestMethod.GET)  
	@ResponseBody  
	public ResponseSupport<Map<String,Object>> process(HttpServletRequest request) throws Exception { 
	  
	    Map<String,Object> map = new HashMap<>();  
	    FileUploadListener.ProcessInfo processInfo = (FileUploadListener.ProcessInfo)request.getSession().getAttribute("proInfo");  
	    map.put("show", processInfo.show);  
	    map.put("rate", processInfo.rate);
		ResponseSupport<Map<String,Object>> responseSupport = new ResponseSupport<Map<String,Object>>();
		responseSupport.setCode(200);
		responseSupport.setMessage("获取到上传进度");
		responseSupport.setContent(map);
	  
	    return responseSupport;  
	}
	
	
}
